package org.jeecg.modules.chat;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import dm.jdbc.util.StringUtil;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.config.shiro.IgnoreAuth;
import org.jeecg.modules.chat.entity.LiveContent;
import org.jeecg.modules.content.entity.JkLiveContent;
import org.jeecg.modules.content.service.IJkLiveContentService;
import org.jeecg.modules.demo.live.entity.JkLive;
import org.jeecg.modules.demo.live.service.IJkLiveService;
import org.jeecg.modules.demo.member.entity.JkMemberInfo;
import org.jeecg.modules.demo.member.service.IJkMemberInfoService;
import org.jeecg.modules.util.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
@ServerEndpoint("/chatWebSocket/{liveId}/{userId}")
public class ChatWebSocket {

    private Session session;
    private String liveId;
    private String userId;
/*    @Autowired
    private IJkLiveService jkLiveService;*/

    private static CopyOnWriteArraySet<ChatWebSocket> chatWebSockets =new CopyOnWriteArraySet<>();
    private static Map<String,Session> sessionPool = new HashMap<String,Session>();


    // 存储结构: 频道ID → (用户ID → 会话)
    private static final ConcurrentHashMap<String, ConcurrentHashMap<String, Session>> channelPool =
            new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session,@PathParam(value = "liveId") String liveId,
                       @PathParam("userId") String userId) {
        try {
            this.session = session;
            this.liveId = liveId;
            this.userId = userId;

          //  chatWebSockets.add(this);
           // sessionPool.put(liveId, session);
           // log.info("【websocket消息】有新的连接，总数为:"+ chatWebSockets.size());
            // 初始化频道或添加用户到频道
            channelPool.computeIfAbsent(liveId, k -> new ConcurrentHashMap<>())
                    .put(userId, session);

            log.info("【频道:{}】用户{}加入，当前在线:{}人",
                    liveId, userId, channelPool.get(liveId).size());
            JkLiveContent liveContent =new JkLiveContent();
            liveContent.setContent("欢迎进入直播间");
            liveContent.setLiveid(liveId);
            liveContent.setUserid(userId);
            liveContent.setCreateby("sys");
            liveContent.setCreatetime(new Date());
            IJkLiveContentService jkLiveContentService = SpringContextUtil.getBean(IJkLiveContentService.class);
            jkLiveContentService.save(liveContent);


            //String message = "{\"message\":\"系统通知: 用户[\" + userId + \"]加入频道\"}";
// 或者使用String.format()
           // String message = String.format("{\"message\":\"系统通知: 用户%s加入频道\"}", userId);

            // 获取size值
            int size = channelPool.get(liveId).size();


            IJkMemberInfoService jkMemberInfoService = SpringContextUtil.getBean(IJkMemberInfoService.class);
            String nickname = "用户"+userId;
            JkMemberInfo memberInfo = jkMemberInfoService.getById(userId);
            if(memberInfo !=null){
                 nickname = memberInfo.getNickname();
                if(StringUtil.isEmpty(nickname)){
                    nickname = "用户"+userId;
                }
            }

// 构造包含userId和size的JSON字符串
        //    String message = String.format("{\"nickName\":\"%s\", \"size\":%d}", nickname, size);
            // 假设 nickname 和 size 已正确赋值
            String message = String.format(
                    "{\"nickName\":\"%s\", \"size\":%d, \"type\":%d}",
                    nickname,
                    size,
                    1  // 新增 type 字段，固定值为 1
            );

            //String message = String.format("{\"userId\":\"%s\"}", userId);
            // 向频道内发送用户加入通知
            broadcast(liveId, message);
            //查询当前频道信息

            LambdaQueryWrapper<JkLiveContent> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JkLiveContent::getLiveid, liveId);
            queryWrapper.orderByDesc(JkLiveContent::getCreatetime);

            Page<JkLiveContent> page = new Page<JkLiveContent>(1, 50);
            IPage<JkLiveContent> list = jkLiveContentService.page(page, queryWrapper);
          //  List<JkLiveContent> list = jkLiveContentService.list(queryWrapper);
            ObjectMapper mapper = new ObjectMapper();
            String jsonResult = mapper.writeValueAsString(list);
          //  String oMessage = String.format("{\"message\": \"%s\"}", jsonResult);
            //新用户得到
            broadcast(liveId,jsonResult);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @OnClose
    public void onClose() {
        try {
           // chatWebSockets.remove(this);
            //log.info("【websocket消息】连接断开，总数为:"+ chatWebSockets.size());
            ConcurrentHashMap<String, Session> users = channelPool.get(liveId);
            if (users != null) {
                users.remove(userId);
                log.info("【频道:{}】用户{}离开，当前在线:{}人",
                        liveId, userId, users.size());
                IJkLiveService jkLiveService = SpringContextUtil.getBean(IJkLiveService.class);
                JkLive jklive=jkLiveService.getById(liveId);
                if(jklive!=null){
                    if(jklive.getMainId().equals(userId)){
                        JkLiveContent liveContent =new JkLiveContent();
                        liveContent.setContent("主播离开直播间");
                        liveContent.setLiveid(liveId);
                        liveContent.setUserid(userId);
                        liveContent.setCreateby("sys");
                        liveContent.setCreatetime(new Date());
                        IJkLiveContentService jkLiveContentService = SpringContextUtil.getBean(IJkLiveContentService.class);
                        jkLiveContentService.save(liveContent);
                          String message = String.format("{\"message\":\"主播[%s]离开直播间\"}", userId);
                          //向频道内发送用户离开通知
                        broadcast(liveId, message);
                    }else {
                       // String message = String.format("{\"message\":\"用户[%s]离开直播间\"}", userId);

                        int size = users.size(); // 获取size值



                        IJkMemberInfoService jkMemberInfoService = SpringContextUtil.getBean(IJkMemberInfoService.class);
                        JkMemberInfo memberInfo = jkMemberInfoService.getById(userId);
                        String nickname = memberInfo.getNickname();
                        if(StringUtil.isEmpty(nickname)){
                            nickname = "用户"+userId;
                        }
// 构造包含userId和size的JSON字符串
                       // String message = String.format("{\"nickName\":\"%s\", \"size\":%d}", nickname, size);

                        // 假设 nickname 和 size 已正确赋值
                        String message = String.format(
                                "{\"nickName\":\"%s\", \"size\":%d, \"type\":%d}",
                                nickname,
                                size,
                                2  // 新增 type 字段，固定值为 1
                        );
                        //向频道内发送用户离开通知
                        broadcast(liveId, message);
                    }
                }


               // String message = String.format("{\"message\":\"系统通知: 用户[%s]离开频道\"}", userId);
                // 向频道内发送用户离开通知
                //broadcast(liveId, message);

                // 如果频道为空，移除频道
                if (users.isEmpty()) {
                    channelPool.remove(liveId);
                }
            }
        } catch (Exception e) {
        }
    }

    @OnMessage
    public void onMessage(String message) {
       // String json = "{\"id\":\"1\",\"userId\":\"11\",\"liveId\":\"22\",\"content\":\"测试内容\"}";
        try {
            log.info("【websocket消息】收到客户端消息:"+message);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            Date currentDate = new Date();
            // 将JSON字符串解析为LiveContent对象
            JkLiveContent liveContent = objectMapper.readValue(message, JkLiveContent.class);
            liveContent.setCreatetime(currentDate);
            IJkLiveContentService jkLiveContentService = SpringContextUtil.getBean(IJkLiveContentService.class);
            jkLiveContentService.save(liveContent);
           // sendAllMessage(liveContent.getContent());
        /*    LambdaQueryWrapper<JkLiveContent> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JkLiveContent::getLiveid, liveId);

            //查询当前频道信息
            List<JkLiveContent> list = jkLiveContentService.list(queryWrapper);
            ObjectMapper mapper = new ObjectMapper();
            String jsonResult = mapper.writeValueAsString(list);*/
          //  String oMessage = String.format("{\"message\": \"%s\"}", message);
            String userid = liveContent.getUserid();
            IJkMemberInfoService jkMemberInfoService = SpringContextUtil.getBean(IJkMemberInfoService.class);
            JkMemberInfo memberInfo = jkMemberInfoService.getById(userid);
           String nickname = "用户"+userid;
            if(memberInfo != null){
                 nickname = memberInfo.getNickname();
                if(StringUtil.isEmpty(nickname)){
                    nickname = "用户"+userid;
                }
                liveContent.setNickName(nickname);
            }

             List<JkLiveContent> list = new ArrayList<>();
            list.add(liveContent);
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(list);  // 转换为 JSON 数组字符串

            broadcast(liveContent.getLiveid(),jsonString);
        }catch (Exception e){
          log.error(e.getMessage());
        }

    }

    // 此为广播消息
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:"+message);
        for(ChatWebSocket chatWebSocket : chatWebSockets) {
            try {
                if(chatWebSocket.session.isOpen()) {
                    chatWebSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null&&session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:"+message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息(多人)
    public void sendMoreMessage(String[] userIds, String message) {
        for(String userId:userIds) {
            Session session = sessionPool.get(userId);
            if (session != null&&session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:"+message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }



    }

    private void broadcast(String liveId, String message) {
        ConcurrentHashMap<String, Session> users = channelPool.get(liveId);
        if (users == null) return;

        users.forEach((userId, session) -> {
            try {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                log.error("【频道:{}】向用户{}发送消息失败", liveId, userId, e);
            }
        });
    }

}

